package io.github.talelin.latticy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.github.talelin.autoconfigure.exception.NotFoundException;
import io.github.talelin.latticy.common.LocalUser;
import io.github.talelin.latticy.common.util.BeanUtils;
import io.github.talelin.latticy.dto.problem.ProblemCreateDTO;
import io.github.talelin.latticy.dto.problem.ProblemPageDTO;
import io.github.talelin.latticy.dto.problem.ShelfDTO;
import io.github.talelin.latticy.mapper.LocationMapper;
import io.github.talelin.latticy.mapper.PickingDetailMapper;
import io.github.talelin.latticy.mapper.ProblemMapper;
import io.github.talelin.latticy.model.*;
import io.github.talelin.latticy.service.ProblemService;
import io.github.talelin.latticy.service.PutAwayService;
import io.github.talelin.latticy.service.feign.OrderFeignService;
import io.github.talelin.latticy.vo.FindResultVO;
import io.github.talelin.latticy.vo.PickingDetailVO;
import io.github.talelin.latticy.vo.ProblemVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName：ProblemServiceImpl
 * @Author: ljj
 * @Date: 2022/8/17 16:05
 */
@Slf4j
@Service
public class ProblemServiceImpl extends ServiceImpl<ProblemMapper, ProblemDO> implements ProblemService {

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private PickingDetailMapper pickingDetailMapper;

    @Autowired
    private PutAwayService putAwayService;

    @Autowired
    private LocationMapper locationMapper;

    @Override
    public void mark(ProblemCreateDTO problemCreateDTO) {
        UserDO localUser = LocalUser.getLocalUser();
        // 根据订单号查询拣货单号
        LambdaQueryWrapper<PickingDetailDO> queryWrapper = Wrappers.lambdaQuery(PickingDetailDO.class)
                .eq(PickingDetailDO::getOrderNo, problemCreateDTO.getOrderNo());
        PickingDetailDO pickingDetailDO = pickingDetailMapper.selectOne(queryWrapper);
        ProblemDO problemDO = BeanUtils.copyProperties(problemCreateDTO, ProblemDO.class);
        problemDO.setPickingNo(pickingDetailDO.getPickingNo());
        problemDO.setCustomerCode(localUser.getUsername());
        FindResultVO findResultVO = orderFeignService.findById(problemCreateDTO.getOrderNo());
        Map<String, Object> data = (Map<String, Object>) findResultVO.getData();
        problemDO.setChannel(MapUtils.getString(data, "logistics"));
        problemDO.setTrackingNo(MapUtils.getString(data, "trackingNo"));
        problemDO.setWarehouseCode(MapUtils.getString(data, "code"));
        problemDO.setReferenceNo(MapUtils.getString(data, "referenceNo"));
        this.baseMapper.insert(problemDO);
    }

    @Override
    public FindResultVO pageList(ProblemPageDTO problemPageDTO) {
        Page<ProblemDO> page = new Page<>(problemPageDTO.getCurrPage(), problemPageDTO.getPageSize());
        LambdaQueryWrapper<ProblemDO> queryWrapper = Wrappers.lambdaQuery(ProblemDO.class)
                .eq(StringUtils.isNotEmpty(problemPageDTO.getWarehouseCode()), ProblemDO::getWarehouseCode, problemPageDTO.getWarehouseCode())
                .eq(problemPageDTO.getType() != null, ProblemDO::getType, problemPageDTO.getType())
                .eq(StringUtils.isNotEmpty(problemPageDTO.getChannel()), ProblemDO::getChannel, problemPageDTO.getChannel())
                .and(CollectionUtils.isNotEmpty(problemPageDTO.getNumbers()),
                        wrapper -> wrapper.in(ProblemDO::getOrderNo, problemPageDTO.getNumbers()).or()
                                .in(ProblemDO::getReferenceNo, problemPageDTO.getNumbers()).or()
                                .in(ProblemDO::getTrackingNo, problemPageDTO.getNumbers()));
        IPage<ProblemDO> iPage = this.baseMapper.selectPage(page, queryWrapper);
        List<ProblemDO> records = iPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return FindResultVO.success();
        }
        List<Long> orderOns = records.stream().map(ProblemDO::getOrderNo).collect(Collectors.toList());
        FindResultVO findResultVO = orderFeignService.findByIds(orderOns);
        if (findResultVO.getData() == null) {
            throw new NotFoundException("数据异常");
        }
        List<Map<String, Object>> data = (List<Map<String, Object>>) findResultVO.getData();
        Map<Long, List<Map<String, Object>>> orderMap = data.stream().collect(Collectors.groupingBy(map -> MapUtils.getLong(map, "order_no")));
        List<ProblemVO> problemVOS = new ArrayList<>();
        for (ProblemDO record : records) {
            ProblemVO problemVO = BeanUtils.copyProperties(record, ProblemVO.class);
            problemVO.setOrderMap(orderMap.get(problemVO.getOrderNo()));
            problemVOS.add(problemVO);
        }
        IPage<ProblemVO> convert =
                iPage.convert(problemDO -> BeanUtils.copyProperties(problemDO, ProblemVO.class));
        convert.setRecords(problemVOS);
        return FindResultVO.success(convert);
    }

    @Override
    public List<PickingDetailVO> dealWith(Long orderNo) {
        LambdaQueryWrapper<PickingDetailDO> queryWrapper = Wrappers.lambdaQuery(PickingDetailDO.class)
                .eq(PickingDetailDO::getOrderNo, orderNo);
        List<PickingDetailDO> pickingDetailDOS = pickingDetailMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(pickingDetailDOS)) {
            return null;
        }
        List<String> collect = pickingDetailDOS.stream().map(PickingDetailDO::getLocation).collect(Collectors.toList());
        List<LocationDO> locationDOS = locationMapper.selectBatchIds(collect);
        Map<Integer, List<LocationDO>> locationMap = locationDOS.stream().collect(Collectors.groupingBy(LocationDO::getId));
        return pickingDetailDOS.stream().map(pickingDetailDO -> {
            PickingDetailVO pickingDetailVO = BeanUtils.copyProperties(pickingDetailDO, PickingDetailVO.class);
            pickingDetailVO.setLocationName(locationMap.get(pickingDetailDO.getLocation()).get(0).getName());
            return pickingDetailVO;
        }).collect(Collectors.toList());
    }

    @Override
    public void shelf(ShelfDTO shelfDTO) {
        FindResultVO findResultVO = orderFeignService.findById(shelfDTO.getOrderNo());
        Map<String, Object> data = (Map<String, Object>) findResultVO.getData();
        List<PutAwayDO> putAwayDOS = shelfDTO.getSkus().stream().map(sku -> {
            PutAwayDO putAwayDO = new PutAwayDO();
            putAwayDO.setWarehouseCode(data.get("code").toString());
            putAwayDO.setLocationId(sku.getLocationId());
            putAwayDO.setSku(sku.getSku());
            putAwayDO.setSkuName(sku.getSkuName());
            putAwayDO.setQuantity(sku.getQuantity());
            return putAwayDO;
        }).collect(Collectors.toList());
        putAwayService.saveBatch(putAwayDOS);
    }
}
